查看原文
其他

ListView的setEmptyView无效问题及源码解析

2017-03-15 androidstarjack 终端研发部



前言介绍


很多童鞋们认为ListView的setEmptyView设置空界面无效的。通常在网上查了查,然后来按照网上的做法直接复制粘贴一下。效果出来就OK了。身为一个开发者,我们既要知其然,也要知道其所以然。

来自androidstarjack博客地址:   


正文

我们通常对ListView列表setEmptyView无效问题目前大部分是这样做的:




setEmptyView()其实是AdapterView的方法,而我们开发中常用到的ListView, GridView, ExpandableListView等都是继承于AdapterView的,所以可以直接调用这个方法。


so问题来了。


为什么一定要加上


这行代码呢?

请看源码:


从上面可以看出当emptyView部位空时,先通过updateEmptyStatus(empty);进行更新当前的View。

在setEmptyView方法中将传过来的emptyView赋值给全局的mEmptyView。在其他地方也可以对其进行处理。

接下来是看一下updateEmptyStatus(empty)的源码:


updateEmptyStatus源码很简单,根据empty这个状态值进行设定mEmptyView 是否显示。 如果adapter不为空,则执行:



为空时的时候:



源码中仅仅只是对mEmptyView进行了隐藏和显示。并未对其进行说明。这就表明了, mEmptyView和当前的listview或者是GridView及其其他View是同一级的关系。同时也说明了为什么需要用到((ViewGroup)llr_recycleView_queryist.getParent()).addView(emptyView); 才能起到效果。

这也可能是Android源码时的一个不足之处。针对于Android上的这些问题有些老司机早就想好了对策。比如说PullToRefreshAdapterViewBase就重写了setemptyView方法。


这既是为什么有些时候不做处理也可以有效果。

对EmptyView的封装


如何调用:



注意:如果你的子布局中有多层父布局进行嵌套,这个时候

((ViewGroup)view.getParent()).addView(this);

这个方法是无效的。addView的时候布局中的大小match_parent是没有效果的,它总是以包裹内容进行填充的。

显示效果:

这个时候一定要调用

((ViewGroup)view.getParent()).addView(this,params);

对整体布局用代码进行设置大小才起到效果。 调用addView(this,params)之后正确显示:

这里的params是最外层的布局大小:


该工具类封装好之后可用于ListView,GridView,RecycleView,PullToRefreshView及其自定义相关的组件的view。直接调用其方法setEmptyView()即可。

曾经踩过的坑:

addView调用之后导致子布局的android:layout_width="match_parent"属性或者 android:layout_width="fll_parent"

((ViewGroup)view.getParent()).addView(params);

属性无效。

我们先看源码addView(View view):

从源码中可以知道,如果不传入 LayoutParams.params的话,就会有一个默认的params。

那么再看看源码:



到这里我们就可以清楚的看到:

如果一个View没有set LayoutParams,在该View被添加到一个ViewGroup里时,ViewGroup会为该View创建一个默认的LayoutParams。所以如果题中的view已经存在于一个ViewGroup中,view.getLayoutParams()便会得到ViewGroup为其创建的默认LayoutParams。而这个默认LayoutParams会因ViewGroup而变,而这里的ViewGroup是指得当前的LinearLayout。LayoutParams是LayoutParams.WRAP_CONTENT将会是子布局的包裹内容。

因此如果只调用addView(View v)不设置params参数将会无效。

SwipeRefreshLayout和ListView的EmptyView共存冲突的问题

最好的方式是: 将ListView和EmptyView分离,让他们两个分别被两个SwipeRefreshLayout包裹

参考链接:

相信自己,没有做不到的,只有想不到的

如果你觉得此文对您有所帮助,欢迎入群 QQ交流群 :232203809 微信公众号:终端研发部


            

Hello,伙伴们

长按二维码就可以关注我们啦!



您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存